package com.xmjs.baselibrary.base.activity.systembar;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;

import com.xmjs.baselibrary.R;
import com.xmjs.baselibrary.base.activity.permission.PermissionActivity;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 该基类的作用：
 * 1.设置系统状态栏的样式
 */
public class SystemBarActivity extends PermissionActivity {
    //默认的系统栏颜色值.
    public static final int DEFAULT_COLOR = 0x99000000;
    //判断导航栏是否存在，1：不存在，0：存在
    private static String navBarOverride;
    //系统配置
    private SystemBarConfig config;
    //状态栏是否可用
    private boolean statusBarAvailable = true;
    //导航栏是否可用
    private boolean navBarAvailable;
    //是否启用系统状态栏
    private boolean statusBarEnabled = true;
    //是否启用系统导航栏
    private boolean navBarEnabled;
    //状态栏
    private View statusBarView;
    //导航栏
    private View navBarView;

    //通过反射获知当前系统是否存在导航栏
    static {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                Class c = Class.forName("android.os.SystemProperties");
                Method m = c.getDeclaredMethod("get", String.class);
                m.setAccessible(true);
                navBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
            } catch (Throwable e) {
                navBarOverride = null;
            }
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //设置透明状态栏
        setTranslucentStatus();

        Window win = getWindow();
        ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //检查样式属性
            int[] attrs = {android.R.attr.windowTranslucentStatus, android.R.attr.windowTranslucentNavigation};
            TypedArray a = obtainStyledAttributes(attrs);
            try {
                statusBarAvailable = a.getBoolean(0, false);
                navBarAvailable = a.getBoolean(0, false);
            } finally {
                a.recycle();
            }

            //检查窗口标记
            WindowManager.LayoutParams winParams = win.getAttributes();
            int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            if ((winParams.flags & bits) != 0) {
                statusBarAvailable = true;
            }
            bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            if ((winParams.flags & bits) != 0) {
                navBarAvailable = true;
            }
        }

        config = new SystemBarConfig(this, statusBarAvailable, navBarAvailable);

        //设备是否存在导航栏
        if (!config.hasNavigtionBar()) {
            navBarAvailable = false;
        }

        if (statusBarAvailable) {
            setupStatusBarView(decorViewGroup);
        }
        if (navBarAvailable) {
            setupNavBarView(decorViewGroup);
        }

        //设置状态栏背景
        setStatusBarResource(setStatusBarResource());
        //设置状态栏高亮模式
        setStatusBarLightMode(this, isStatusBarLightMode());
    }

    /**
     * 设置状态栏颜色
     *
     * @return
     */
    public int setStatusBarResource() {
        return R.color.transparent;
    }

    /**
     * 状态栏高亮模式(字体，图标均为黑色)
     *
     * @return
     */
    public boolean isStatusBarLightMode() {
        return true;
    }

    /**
     * 是否启用系统状态栏
     *
     * @return
     */
    public boolean isStatusBarEnabled() {
        return statusBarEnabled;
    }

    /**
     * 是否启用系统导航栏
     *
     * @return
     */
    public boolean isNavBarEnabled() {
        return navBarEnabled;
    }

    /**
     * 获得状态栏的高度
     *
     * @return
     */
    public int getStatusBarHeight() {
        Resources resources = getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }

    /**
     * 代码实现android:fitsSystemWindows
     *
     * @param activity
     */
    private void setRootViewFitsSystemWindows(Activity activity, boolean fitSystemWindows) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            ViewGroup winContent = (ViewGroup) activity.findViewById(android.R.id.content);
            if (winContent.getChildCount() > 0) {
                ViewGroup rootView = (ViewGroup) winContent.getChildAt(0);
                if (rootView != null) {
                    rootView.setFitsSystemWindows(fitSystemWindows);
                }
            }
        }
    }

    /**
     * 修改状态栏颜色，支持4.4以上版本
     *
     * @param colorId 颜色
     */
    private void setStatusBarColor2(int colorId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.setStatusBarColor(getResources().getColor(colorId));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            setTranslucentStatus();//状态栏设置为透明
            setStatusBarEnabled(true);//显示状态栏
            setStatusBarColor(colorId);//设置状态栏颜色
        }
    }

    /**
     * 设置透明状态栏
     */
    private void setTranslucentStatus() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //5.x开始需要把颜色设置透明，否则导航栏会呈现系统默认的浅灰色
            Window window = getWindow();
            View decorView = window.getDecorView();
            //两个 flag 要结合使用，表示让应用的主体内容占用系统状态栏的空间
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            // window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
            //导航栏颜色也可以正常设置
            //window.setNavigationBarColor(Color.TRANSPARENT);
        } else {
            Window window = getWindow();
            WindowManager.LayoutParams attributes = window.getAttributes();
            int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            attributes.flags |= flagTranslucentStatus;
            //int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            //attributes.flags |= flagTranslucentNavigation;
            window.setAttributes(attributes);
        }
    }

    /**
     * 设置是否启用系统状态栏
     * <p>
     * 如果平台正在运行Jelly Bean或更早的版本，或者主题或窗口标志中都没有启用半透明的系统UI模式，则此方法不执行任何操作。
     *
     * @param enabled
     */
    private void setStatusBarEnabled(boolean enabled) {
        statusBarEnabled = enabled;
        if (statusBarAvailable) {
            statusBarView.setVisibility(enabled ? View.VISIBLE : View.GONE);
        }
    }

    /**
     * 设置是否启用系统导航栏
     * <p>
     * 如果平台没有软导航键，正在运行Jelly Bean或更早，或者在主题或窗口标志中都没有启用半透明的系统UI模式，则此方法不执行任何操作。
     *
     * @param enabled
     */
    private void setNavigationBarEnabled(boolean enabled) {
        navBarEnabled = enabled;
        if (navBarAvailable) {
            navBarView.setVisibility(enabled ? View.VISIBLE : View.GONE);
        }
    }

    /**
     * 设置状态栏颜色
     *
     * @param color
     */
    private void setStatusBarColor(int color) {
        if (statusBarAvailable) {
            statusBarView.setBackgroundColor(getResources().getColor(color));
        }
    }

    /**
     * 设置状态栏的背景
     *
     * @param res
     */
    private void setStatusBarResource(int res) {
        if (statusBarAvailable) {
            statusBarView.setBackgroundResource(res);
        }
    }

    /**
     * 设置状态栏的绘制资源
     *
     * @param drawable
     */
    private void setStatusBarDrawable(Drawable drawable) {
        if (statusBarAvailable) {
            statusBarView.setBackgroundDrawable(drawable);
        }
    }

    /**
     * 设置状态栏的透明度
     *
     * @param alpha
     */
    @TargetApi(11)
    private void setStatusBarAlpha(float alpha) {
        if (statusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            statusBarView.setAlpha(alpha);
        }
    }

    /**
     * 设置导航栏的背景色
     *
     * @param color
     */
    private void setNavigationBarColor(int color) {
        if (navBarAvailable) {
            navBarView.setBackgroundColor(color);
        }
    }

    /**
     * 设置导航栏的背景
     *
     * @param res
     */
    private void setNavigationBarResource(int res) {
        if (navBarAvailable) {
            navBarView.setBackgroundResource(res);
        }
    }

    /**
     * 设置导航栏背景
     *
     * @param drawable
     */
    @SuppressWarnings("deprecation")
    private void setNavigationBarDrawable(Drawable drawable) {
        if (navBarAvailable) {
            navBarView.setBackgroundDrawable(drawable);
        }
    }

    /**
     * 设置导航栏的透明度
     *
     * @param alpha
     */
    @TargetApi(11)
    private void setNavigationBarAlpha(float alpha) {
        if (navBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            navBarView.setAlpha(alpha);
        }
    }

    /**
     * 获取状态栏配置
     *
     * @return
     */
    private SystemBarConfig getConfig() {
        return config;
    }

    /**
     * 设置状态栏视图
     *
     * @param decorViewGroup
     */
    private void setupStatusBarView(ViewGroup decorViewGroup) {
        statusBarView = new View(this);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 200);
        params.gravity = Gravity.TOP;
        if (navBarAvailable && !config.isNavigationAtBottom()) {
            params.rightMargin = config.getNavigationBarWidth();
        }
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(DEFAULT_COLOR);
        statusBarView.setVisibility(View.GONE);
        decorViewGroup.addView(statusBarView);
    }

    /**
     * 设置状态栏的高亮模式
     * （默认黑色，适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android）
     *
     * @param activity
     * @param isDark   是否是黑色字体和图标
     * @return
     */
    private int setStatusBarLightMode(Activity activity, boolean isDark) {
        int result = 0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (MIUISetStatusBarLightMode(activity, isDark)) {//小米
                result = 1;
            } else if (FlymeSetStatusBarLightMode(activity.getWindow(), isDark)) {//魅族
                result = 2;
            } else if (Build.MANUFACTURER.equalsIgnoreCase("OPPO")) {//OPPO
                setOPPOStatusTextColor(activity, isDark);
                result = 3;
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Android6.0以上系统
                if (isDark) {
                    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                } else {
                    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_VISIBLE);
                }
                result = 4;
            }
        }
        return result;
    }

    private static final int SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT = 0x00000010;

    /**
     * 设置OPPO状态栏文字颜色是否为黑色
     *
     * @param activity
     * @param lightStatusBar
     */
    private static void setOPPOStatusTextColor(Activity activity, boolean lightStatusBar) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        int vis = window.getDecorView().getSystemUiVisibility();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (lightStatusBar) {
                vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (lightStatusBar) {
                vis |= SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
            } else {
                vis &= ~SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
            }
        }
        window.getDecorView().setSystemUiVisibility(vis);
    }

    /**
     * 设置魅族状态栏文字是否为黑色
     *
     * @param window 需要设置的窗口
     * @param dark   是否把状态栏文字及图标颜色设置为深色
     * @return boolean 成功执行返回true
     */
    private boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {

            }
        }
        return result;
    }

    /**
     * 设置小米状态栏字体是否为黑色（需要MIUIV6以上）
     *
     * @param activity
     * @param dark     是否把状态栏文字及图标颜色设置为深色
     * @return boolean 成功执行返回true
     */
    private boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
        boolean result = false;
        Window window = activity.getWindow();
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result = true;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //开发版 7.7.13 及以后版本采用了系统API，旧方法无效但不会报错，所以两个方式都要加上
                    if (dark) {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    } else {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_VISIBLE);
                    }
                }
            } catch (Exception e) {

            }
        }
        return result;
    }

    /**
     * 设置导航栏视图
     *
     * @param decorViewGroup
     */
    private void setupNavBarView(ViewGroup decorViewGroup) {
        navBarView = new View(this);
        FrameLayout.LayoutParams params;
        if (config.isNavigationAtBottom()) {
            params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, config.getNavigationBarHeight());
            params.gravity = Gravity.BOTTOM;
        } else {
            params = new FrameLayout.LayoutParams(config.getNavigationBarWidth(), FrameLayout.LayoutParams.MATCH_PARENT);
            params.gravity = Gravity.RIGHT;
        }
        navBarView.setLayoutParams(params);
        navBarView.setBackgroundColor(DEFAULT_COLOR);
        navBarView.setVisibility(View.GONE);
        decorViewGroup.addView(navBarView);
    }

    /**
     * 系统配置
     */
    private static class SystemBarConfig {

        private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
        private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
        private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
        private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
        private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";

        private final boolean mTranslucentStatusBar;
        private final boolean mTranslucentNavBar;
        private final int mStatusBarHeight;
        private final int mActionBarHeight;
        private final boolean mHasNavigationBar;
        private final int mNavigationBarHeight;
        private final int mNavigationBarWidth;
        private final boolean mInPortrait;
        private final float mSmallestWidthDp;

        private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
            Resources res = activity.getResources();
            mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
            mSmallestWidthDp = getSmallestWidthDp(activity);
            mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
            mActionBarHeight = getActionBarHeight(activity);
            mNavigationBarHeight = getNavigationBarHeight(activity);
            mNavigationBarWidth = getNavigationBarWidth(activity);
            mHasNavigationBar = (mNavigationBarHeight > 0);
            mTranslucentStatusBar = translucentStatusBar;
            mTranslucentNavBar = traslucentNavBar;
        }

        @TargetApi(14)
        private int getActionBarHeight(Context context) {
            int result = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                TypedValue tv = new TypedValue();
                context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
                result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
            }
            return result;
        }

        @TargetApi(14)
        private int getNavigationBarHeight(Context context) {
            Resources res = context.getResources();
            int result = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                if (hasNavBar(context)) {
                    String key;
                    if (mInPortrait) {
                        key = NAV_BAR_HEIGHT_RES_NAME;
                    } else {
                        key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
                    }
                    return getInternalDimensionSize(res, key);
                }
            }
            return result;
        }

        @TargetApi(14)
        private int getNavigationBarWidth(Context context) {
            Resources res = context.getResources();
            int result = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                if (hasNavBar(context)) {
                    return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
                }
            }
            return result;
        }

        @TargetApi(14)
        private boolean hasNavBar(Context context) {
            Resources res = context.getResources();
            int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
            if (resourceId != 0) {
                boolean hasNav = res.getBoolean(resourceId);
                // check override flag (see static block)
                if ("1".equals(navBarOverride)) {
                    hasNav = false;
                } else if ("0".equals(navBarOverride)) {
                    hasNav = true;
                }
                return hasNav;
            } else { // fallback
                return !ViewConfiguration.get(context).hasPermanentMenuKey();
            }
        }

        private int getInternalDimensionSize(Resources res, String key) {
            int result = 0;
            int resourceId = res.getIdentifier(key, "dimen", "android");
            if (resourceId > 0) {
                result = res.getDimensionPixelSize(resourceId);
            }
            return result;
        }

        @SuppressLint("NewApi")
        private float getSmallestWidthDp(Activity activity) {
            DisplayMetrics metrics = new DisplayMetrics();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
            } else {
                activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            }
            float widthDp = metrics.widthPixels / metrics.density;
            float heightDp = metrics.heightPixels / metrics.density;
            return Math.min(widthDp, heightDp);
        }

        /**
         * 判断系统导航栏是否在屏幕底部
         *
         * @return
         */
        public boolean isNavigationAtBottom() {
            return (mSmallestWidthDp >= 600 || mInPortrait);
        }

        /**
         * 获取系统状态栏高度
         *
         * @return
         */
        public int getStatusBarHeight() {
            return mStatusBarHeight;
        }

        /**
         * 获取ActionBar的高度
         *
         * @return
         */
        public int getActionBarHeight() {
            return mActionBarHeight;
        }

        /**
         * 该设备是否存在系统导航栏
         *
         * @return
         */
        public boolean hasNavigtionBar() {
            return mHasNavigationBar;
        }

        /**
         * 获取系统导航栏的高度
         *
         * @return
         */
        public int getNavigationBarHeight() {
            return mNavigationBarHeight;
        }

        /**
         * 获取系统导航栏在屏幕上的宽度
         *
         * @return
         */
        public int getNavigationBarWidth() {
            return mNavigationBarWidth;
        }

    }
}
